home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / match-nshell.hqx / match / source / match.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-01  |  9.0 KB  |  393 lines

  1. /* ========== the commmand file: ==========
  2.  
  3.     match.c
  4.     
  5.     Copyright (c) 1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #define    MATCH_BUF_SIZE    2048
  16.  
  17. #ifdef __MWERKS__            // CodeWarrior requires an A4 setup
  18. #include <A4Stuff.h>
  19. #endif
  20.  
  21. #include <script.h>
  22. #include <string.h>
  23.  
  24. #include "nshc.h"
  25.  
  26. #include "arg_utl.proto.h"
  27. #include "fss_utl.proto.h"
  28. #include "fss_utl2.proto.h"
  29. #include "nshc_utl.proto.h"
  30. #include "str_utl.proto.h"
  31.  
  32. // data definition - this struct is the root of all data
  33.  
  34. typedef struct {
  35.  
  36.     int        by_file;        // 1 if files are listed, 0 if stdin
  37.     int        got_fss;        // 1 if FSSpec calls are available
  38.     int        arg;            // next file to process in arg list
  39.     short    p_arg;            // position of '-p' in arg list
  40.     short    fref;            // file ref. number, 0 if no file open
  41.     Str255    pattern;        // the pattern for which we search
  42.     Str255    line;            // the line we are currently looking at
  43.     int        line_pos;        // the place to put the next char in 'line'
  44.  
  45. } t_match_data;
  46.  
  47. typedef    t_match_data    **MData;
  48.  
  49. /* ======================================== */
  50.  
  51. // prototypes - utility
  52.  
  53. void match_bad( t_nshc_parms *nshc_parms, int code );
  54. void match_bad_file( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg );
  55. void match_good( t_nshc_parms *nshc_parms );
  56.  
  57. // prototypes - file copy routines
  58.  
  59. void match_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_data **mData );
  60. void match_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_data **mData );
  61.  
  62. // prototypes - console copy routines
  63.  
  64. void match_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_data **mData );
  65.  
  66. // prototypes - state machine
  67.  
  68. void match_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  );
  69. void match_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  70. void match_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  71.  
  72. /* ======================================== */
  73.  
  74. // utility routines
  75.  
  76. /* ======================================== */
  77.  
  78. void match_bad(  t_nshc_parms *nshc_parms, int code )
  79. {
  80.     nshc_parms->action = nsh_stop;
  81.     nshc_parms->result = code;
  82. }
  83.  
  84. void match_bad_file(  t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg )
  85. {
  86.     nshc_calls->NSH_putStr_err("\pmatch: File access error (");
  87.     nshc_calls->NSH_putStr_err(msg);
  88.     nshc_calls->NSH_putStr_err("\p)\r");
  89.  
  90.     nshc_parms->action = nsh_stop;
  91.     nshc_parms->result = NSHC_ERR_GENERAL;
  92. }
  93.  
  94. void match_good(  t_nshc_parms *nshc_parms )
  95. {
  96.     nshc_parms->action = nsh_stop;
  97.     nshc_parms->result = 0;
  98. }
  99.  
  100. /* ======================================== */
  101.  
  102. // file access routines
  103.  
  104. /* ======================================== */
  105.  
  106. void match_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_data **mData )
  107. {
  108.     int        result;
  109.     long    dirID;
  110.     Boolean    isDir;
  111.     FSSpec    fss;
  112.     
  113.     (**mData).fref = 0;
  114.     (**mData).line_pos = 0;
  115.  
  116.     // =====> skip the -p option
  117.     
  118.     if ( (**mData).arg == (**mData).p_arg )
  119.         (**mData).arg += 2;
  120.         
  121.     if ( (**mData).arg >= nshc_parms->argc ) {
  122.         match_good( nshc_parms );
  123.         return;
  124.         }
  125.     
  126.     // =====> convert path to fsspec
  127.     
  128.     result = arg_to_fss( nshc_parms, nshc_calls, (**mData).arg, &fss );
  129.  
  130.     (**mData).arg++;
  131.     
  132.     if (result) {
  133.         match_bad( nshc_parms, result );
  134.         return;
  135.         }
  136.     
  137.     result = fss_to_DirID( &fss, &dirID, &isDir );
  138.         
  139.     if (( result == noErr) && isDir)
  140.         return;
  141.             
  142.     if ( result == fnfErr ) {
  143.         nshc_calls->NSH_putStr_err("\pmatch: File not found = ");
  144.         nshc_calls->NSH_putStr_err((StringPtr)fss.name);
  145.         nshc_calls->NSH_putchar('\r');
  146.         return;
  147.         }
  148.             
  149.     if (!result)
  150.         result = fss_OpenDF((**mData).got_fss, &fss, fsRdPerm, &(**mData).fref);
  151.     
  152.     if ( result ) {
  153.         match_bad_file( nshc_parms, nshc_calls, (StringPtr)fss.name );
  154.         return;
  155.         }
  156. }
  157.  
  158. /* ======================================== */
  159.  
  160. void match_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_data **mData )
  161. {
  162.     char    c;
  163.     int        close;
  164.     int        i,j;
  165.     int        temp;
  166.     int        result;
  167.     long    bcount;
  168.     char    buf[MATCH_BUF_SIZE+1];
  169.     char    *filename;
  170.     
  171.     result = close = 0;
  172.     
  173.     // =====> copy the data fork
  174.     
  175.     bcount = MATCH_BUF_SIZE;
  176.     result = FSRead( (**mData).fref, &bcount, &buf );
  177.     
  178.     if (( result == noErr ) || ( result == eofErr )) {
  179.     
  180.         if (result == eofErr) {
  181.             close = 1;
  182.             result = 0;
  183.             }
  184.         
  185.         if (bcount) {
  186.             j = (**mData).line_pos;
  187.             for ( i = 0 ; i < bcount ; i++ ) {
  188.                 c = buf[i];
  189.                 if ( c && ( c != '\r' ) && ( j < 255 ) )
  190.                     (**mData).line[++j] = c;
  191.                 else {
  192.                     (**mData).line[0] = j;
  193.                     HLock( mData );
  194.                     if ( !nshc_calls->NSH_match( (**mData).pattern, (**mData).line ) ) {
  195.                         filename = &nshc_parms->arg_buf[nshc_parms->argv[(**mData).arg-1]];
  196.                         nshc_calls->NSH_puts( filename );
  197.                         nshc_calls->NSH_putStr( "\p: " );
  198.                         nshc_calls->NSH_putStr( (**mData).line );
  199.                         nshc_calls->NSH_putchar( '\r' );
  200.                         }
  201.                     HUnlock( mData );
  202.                     j = 0;
  203.                     }
  204.                 }
  205.             (**mData).line_pos = j;
  206.             }
  207.     
  208.         }
  209.     else
  210.         match_bad_file( nshc_parms, nshc_calls, "\pread data" );
  211.     
  212.     // =====> close the input file
  213.     
  214.     if (close) {
  215.  
  216.         if ( (**mData).fref ) {
  217.             if ( temp = FSClose( (**mData).fref ) )
  218.                 result = temp;
  219.             (**mData).fref = 0;
  220.             }
  221.             
  222.         if (result)
  223.             match_bad_file( nshc_parms, nshc_calls, "\pclose file" );
  224.                 
  225.         }
  226. }
  227.  
  228. /* ======================================== */
  229.  
  230. // console access routines
  231.  
  232. /* ======================================== */
  233.  
  234. void match_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_data **mData )
  235. {
  236.     long    bcount;
  237.     Str255    buf;
  238.     char    c;
  239.     int        i;
  240.     int        temp;
  241.     
  242.     bcount = nshc_calls->NSH_getStr( buf );
  243.     
  244.     if (!bcount) return;            // wait for characters
  245.     
  246.     if ( !nshc_calls->NSH_match( (**mData).pattern, buf ) )
  247.         nshc_calls->NSH_putStr( buf );    // display the line
  248.     
  249.     if ( bcount == -1 )                // end of input, set-up for exit
  250.         match_good( nshc_parms );
  251. }
  252.  
  253. /* ======================================== */
  254.  
  255. // state machine - core routines
  256.  
  257. /* ======================================== */
  258.  
  259. void match_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  )
  260. {
  261.     int        arg;
  262.     char     *p;
  263.     MData    mData;    // handle to hold our data
  264.     
  265.     nshc_parms->action = nsh_continue;
  266.  
  267.     mData = (MData)NewHandleClear(sizeof(t_match_data));
  268.     
  269.     if (mData) {
  270.         nshc_parms->data = (Handle)mData;            // save the handle to our data
  271.         (**mData).arg = 1;                            // start at the arg = 1 position
  272.         (**mData).by_file = nshc_parms->argc > 3;    // if we have other args, do file i/o
  273.         (**mData).got_fss = fss_test();                // test if we can use FSSpec calls
  274.  
  275.         arg = nshc_got_option( nshc_parms, 'p' );    // get the position of '-p' arg
  276.         (**mData).p_arg = arg;                    // and save it
  277.         
  278.         if ( arg && ( ++arg < nshc_parms->argc ) ) {
  279.             p = &nshc_parms->arg_buf[nshc_parms->argv[arg]];
  280.             if ( cStrLen( p ) < 253 ) {
  281.                 (**mData).pattern[0] = 1;
  282.                 (**mData).pattern[1] = '*';
  283.                 pStrAppendC( (**mData).pattern, p );
  284.                 pStrAppendC( (**mData).pattern, "*" );
  285.                 }
  286.             else {
  287.                 nshc_calls->NSH_putStr_err( "\pmatch: Pattern is too long.\r" );
  288.                 match_bad( nshc_parms, NSHC_ERR_PARMS );
  289.                 }
  290.             }
  291.         else {
  292.             nshc_calls->NSH_putStr_err( "\pUsage: match -p pattern [files...]\r" );
  293.             match_bad( nshc_parms, NSHC_ERR_PARMS );
  294.             }
  295.         
  296.         }
  297.     else {
  298.         nshc_calls->NSH_putStr_err( "\pmatch: Could not allocate storage.\r" );
  299.         match_bad( nshc_parms, NSHC_ERR_MEMORY );
  300.         }
  301. }
  302.  
  303. /* ======================================== */
  304.  
  305. void match_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  306. {
  307.     MData    mData;
  308.  
  309.     if (mData = (MData)nshc_parms->data) {
  310.  
  311.         if ( (**mData).by_file ) {
  312.         
  313.             // if we are not in the middle of a file, open one
  314.  
  315.             if ( !(**mData).fref )
  316.                 match_open( nshc_parms, nshc_calls, mData );
  317.  
  318.             // read and write some of the open file
  319.  
  320.             if ( (**mData).fref )
  321.                 match_read_write( nshc_parms, nshc_calls, mData );
  322.  
  323.             // and see if we are done
  324.  
  325.             if ( !(**mData).fref && ( (**mData).arg >= nshc_parms->argc ) )
  326.                 match_good( nshc_parms );
  327.                 
  328.             }
  329.         else
  330.             match_console( nshc_parms, nshc_calls, mData );
  331.  
  332.         }
  333. }
  334.  
  335. /* ======================================== */
  336.  
  337. void match_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  338. {
  339.     short    fRef;
  340.     MData    mData;
  341.     int        temp;
  342.     int        result;
  343.     
  344.     result = 0;
  345.     
  346.     if (mData = (MData)nshc_parms->data) {
  347.     
  348.         if ( (**mData).fref ) {
  349.             if ( temp = FSClose( (**mData).fref ) )
  350.                 result = temp;
  351.             (**mData).fref = 0;
  352.             }
  353.             
  354.         DisposeHandle(nshc_parms->data);
  355.         }
  356.         
  357.     if (result)
  358.         match_bad_file( nshc_parms, nshc_calls, "\pclosing files" );
  359.         
  360.     nshc_parms->action = nsh_idle;
  361. }
  362.  
  363. /* ======================================== */
  364.  
  365. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  366. {
  367. #ifdef __MWERKS__
  368.     long oldA4  = SetCurrentA4();
  369. #endif
  370.     
  371.     if ( !nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION ) ) {
  372.     
  373.         switch (nshc_parms->action) {
  374.             case nsh_start:
  375.                 match_start(nshc_parms, nshc_calls);
  376.                 break;
  377.             case nsh_continue:
  378.                 match_continue(nshc_parms, nshc_calls);
  379.                 break;
  380.             case nsh_stop:
  381.                 match_stop(nshc_parms, nshc_calls);
  382.                 break;
  383.             }
  384.         
  385.         }
  386.  
  387. #ifdef __MWERKS__
  388.     SetA4(oldA4);
  389. #endif
  390. }
  391.  
  392. /* ======================================== */
  393.